<template>
  <div class="v-EWX _border g-pd-lr-16 g-pd-tb-8 g-flex-1 g-m-t-24">
    <div>
      <component :is="renderDropdown(scenarios, getTargetItem(scenarios, result.scenarioId), i => (result.scenarioId = i.id), true)" />
    </div>
    <el-row class="g-m-t-8">
      <el-col :span="12">
        <component :is="renderDropdown(properties, getTargetItem(properties, result.propertyKey), i => (result.propertyKey = i.id))" />
      </el-col>
      <el-col :span="12">
        <component :is="renderDropdown(connections, getTargetItem(connections, result.connection), i => (result.connection = i.id))" />
      </el-col>
    </el-row>
    <el-row class="g-m-t-16">
      <el-col :span="24">
        <el-row
          v-for="(item, index) in result.conditions"
          :key="index"
        >
          <el-col :span="7">
            <component :is="renderDropdown(models, getTargetItem(models, item.modelId1), i => (item.modelId1 = i.id))" />
          </el-col>
          <el-col :span="7">
            <component
              :is="
                result.propertyKey === 1
                  ? renderDropdown(relations, getTargetItem(relations, item.relation), i => (item.relation = i.id))
                  : renderDropdown(models, getTargetItem(models, item.modelId2), i => (item.modelId2 = i.id))
              "
            />
          </el-col>
          <el-col :span="7">
            <el-input-number
              v-model="item.value"
              :precision="(result.propertyKey - 1) * 8"
              :controls="false"
            ></el-input-number>
          </el-col>
          <el-col :span="3">
            <el-button
              :disabled="result.conditions.length === 1"
              @click="handleDelete(index)"
            >
              <img src="statics/home/canvasreduce.svg" />
            </el-button>
            <el-button @click="handleAdd(index)"><img src="statics/home/canvasmagnify.svg" /></el-button>
          </el-col>
        </el-row>
      </el-col>
    </el-row>
  </div>
</template>

<script lang="ts" setup>
import MDropdown from "@/common/dropdown/Dropdown.vue";
import MDropdownMenuItem from "@/common/dropdown/DropdownMenuItem.vue";
import { modelService } from "@/modules/model/service";
import { cloneDeep } from "lodash";
import { h, watch, onBeforeMount, ref } from "vue";

interface EWXConditionType {
  modelId1: string;
  modelId2?: string;
  relation?: ">" | "<" | "==" | ">=" | "<=" | "!=";
  value: number;
}
interface EWXResultType {
  scenarioId: string;
  propertyKey: 1 | 2;
  connection: 1 | 2;
  conditions: EWXConditionType[] & { _default: EWXConditionType };
}
interface EWXNameType {
  name: string;
}
interface EWXScenarioType extends EWXNameType {
  id: EWXResultType["scenarioId"];
  icon: string;
}
interface EWXModelType extends EWXNameType {
  id: string;
  icon: string;
}
interface EWXPropertyType extends EWXNameType {
  id: EWXResultType["propertyKey"];
}
interface EWXRelationType extends EWXNameType {
  id: EWXConditionType["relation"];
}
interface EWXConnectionType extends EWXNameType {
  id: EWXResultType["connection"];
}

const props = defineProps<{ modelValue: string }>();
const emits = defineEmits<{ (event: "update:modelValue", data: string): void }>();
/** 供选择数据 */
const scenarios = generateEWXArray<EWXScenarioType>([], { id: "", name: "选择想定场景", icon: "" }); // 场景
const models = generateEWXArray<EWXModelType>([], { id: "", name: "选择模型", icon: "" }); // 模型
const properties = generateEWXArray<EWXPropertyType>([
  { id: 1, name: "平台下探测的目标数量" },
  { id: 2, name: "平台与指定目标的距离" }
]); // 模型属性
const relations = generateEWXArray<EWXRelationType>([
  { id: ">", name: ">" },
  { id: "<", name: "<" },
  { id: "==", name: "=" },
  { id: ">=", name: ">=" },
  { id: "<=", name: "<=" },
  { id: "!=", name: "≠" }
]); // 关系
const connections = generateEWXArray<EWXConnectionType>([
  { id: 1, name: "并且" },
  { id: 2, name: "或者" }
]); // 连接
/** 供选择数据 */
/** 返回结果 */
const result = ref<EWXResultType>({
  scenarioId: "",
  propertyKey: 1,
  connection: 1,
  conditions: generateEWXArray<EWXConditionType>([], { modelId1: "", modelId2: "", relation: ">", value: 0 })
});
const modelsMap = new Map<string, EWXModelType[]>();

/** 想定场景改变之后，需要切换models数据源 */
watch(
  () => result.value.scenarioId,
  newVal => {
    models.splice(0);
    const mid = modelsMap.get(newVal);
    mid && models.push(...mid);
  }
);
/** 这里需要过滤掉空数据 */
watch(
  result,
  newVal => {
    const mid = {
      scenarioId: newVal.scenarioId,
      propertyKey: newVal.propertyKey,
      connection: newVal.connection,
      conditions: newVal.conditions
        .filter(condition => condition.modelId1 && condition.value)
        .map(condition => ({
          modelId1: condition.modelId1,
          modelId2: condition.modelId2,
          relations: condition.relation,
          value: String(condition.value)
        }))
    };
    emits("update:modelValue", JSON.stringify(mid));
  },
  { deep: true }
);

/**
 * @param data 下拉列表数据源
 * @param displayItem 展示内容项
 * @param onClick 点击事件
 * @param showIcon 是否展示图标（前提是数据必须有icon属性）
 */
function renderDropdown<T extends EWXNameType>(data: T[], displayItem: T, clickFn: (T) => void, showIcon = false) {
  return h(
    MDropdown,
    { class: "_border _height g-pointer g-ai-c g-pd-lr-8" },
    {
      default: () => [
        showIcon ? h("img", { src: (displayItem as any).icon }) : "", // (displayItem as any)是唯一冲突域
        h("span", { class: "g-flex-1" }, displayItem.name),
        h("img", { src: "statics/icons/app/iconlist2.png" })
      ],
      dropdown: () =>
        data.map((i, index) =>
          h(MDropdownMenuItem, { key: index, onClick: () => clickFn(i) }, () => [
            showIcon ? h("img", { src: (i as any).icon }) : "",
            i["name"]
          ])
        )
    }
  );
}
/**
 * 根据id获取展示内容，如果没有找到，会返回默认内容
 * @param data
 * @param id 所有数据体均使用此属性key并与EWXResultType进行交互
 */
function getTargetItem<T>(data: Array<T> & { _default: T }, id: any) {
  const mid = data.find(i => i["id"] === id);
  return mid || data._default;
}
/** 生成特定数组 */
function generateEWXArray<T>(data: T[], _default: T = data[0]) {
  const res = Array.from(data) as Array<T> & { _default: T };
  res._default = _default;
  return res;
}

function handleAdd(index: number) {
  result.value.conditions.splice(index + 1, 0, cloneDeep(result.value.conditions[index]));
}

function handleDelete(index: number) {
  result.value.conditions.splice(index, 1);
}

onBeforeMount(async () => {
  // 获取想定场景
  const scenariosData = await modelService.getSelectOptions({
    projectId: app.activeProject!.id,
    key: "",
    instanceId: "16902438067776",
    checkMethod: "",
    moreBtnCondition: "16902438067776",
    page: 0,
    size: 100,
    keyword: ""
  });
  // 根据想定场景轮询获取想定模型（后端应该将此接口与上面接口合并为同一个！）
  for (const item of scenariosData) {
    scenarios.push({ id: item.id, icon: item.icon, name: item.label });
    await modelService.queryScenarioAllSpaceResources(app.activeProject!.id, item.id).then(data => {
      modelsMap.set(
        item.id,
        data.map(i => ({ id: i.instanceId, icon: "", name: i.name }))
      );
    });
  }
  // 加载值
  if (props.modelValue) {
    const codeJSON = JSON.parse(props.modelValue) as EWXResultType;
    codeJSON.scenarioId && (result.value.scenarioId = codeJSON.scenarioId);
    codeJSON.propertyKey && (result.value.propertyKey = codeJSON.propertyKey);
    codeJSON.connection && (result.value.connection = codeJSON.connection);
    codeJSON.conditions &&
      result.value.conditions.push(
        ...codeJSON.conditions.map(condition => ({
          modelId1: condition.modelId1,
          modelId2: condition.modelId2,
          relation: condition.relation,
          value: Number(condition.value)
        }))
      ); // 不可以使用Object.assign，会使其丢失_default特征
  }
  if (result.value.conditions.length === 0) result.value.conditions.push(cloneDeep(result.value.conditions._default));
});
</script>

<style lang="scss">
.v-EWX {
  background: #ffffff;
  font-size: 14px;
  ._height {
    height: 30px;
    line-height: 30px;
  }
  .el-input {
    height: 30px;
    font-size: inherit;
  }
  .el-input-number {
    width: 100%;
  }
  .el-button {
    padding: 0;
    border: none;
    height: 30px;
    width: 30px;
  }
}
._border {
  border: 1px solid #e4e3e3;
}
</style>
